/**
 * @file drv_misc.c
 * @brief 智慧电源私有杂项驱动
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 1.0
 * @date 2020-10-28
 * @copyright Copyright (c) 2020  烽火通信
 ***************************************************************
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version  <th>Author  <th>Description
 * <tr><td>2020-10-28 <td>1.0      <td>wangh   <td>内容
 * </table>
 */ 
#include "drv_misc.h"
#include "project_board.h"

#undef LOG_LEVEL_
#define LOG_LEVEL_ 	LOG_LVL_DEBUG
#include "bsp_log.h"

/**
 * @brief 热敏电阻(MF52502J3470)电压温度转换 \n
 * T1 = 1 / ( log(Rt/R)/B + 1/T2 )
 * @param[in]  obj      adc通道对象
 */
#include "math.h"
static float ntc_get_temp( Adc_t *obj)
{
    float vol = AdcReadChannelVol( obj );

    float Rp = 5000;        /* T2常温下的标称阻值 */
    float T2 = 273.15 + 25; /* 常温开尔文温度 */
    float Bx = 3470;        /* B值 */
    float Ka = 273.15;

    float Rt = (vol * 10000) / (3.3 - vol);   /* 电阻值 */

    return (float)( 1/(1/T2 + log(Rt/Rp)/Bx) - Ka + 0.5 );
}

/**
 * @brief 智慧电源ADC检测初始化
 * @param  obj         电源ADC检测对象
 */
int8_t drv_pcuAdc_init( pcuAdc_t *obj )
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;
    
    if (obj->IsInitialized)
    {
        log_e( "drv_pcuAdc_init error: has already Initialized\r\n" );
        return BSP_ERROR_ALREADY_INIT;
    }

    obj->Lock = xSemaphoreCreateBinary();  /* 初始时信号值为0 */
    if(obj->Lock == NULL)
        return BSP_ERROR_NO_MEM;
    xSemaphoreGive( obj->Lock );

    AdcInitChannel( &obj->ADC_TC_obj, ADC_TC );
    AdcInitChannel( &obj->ADC_12V_obj, ADC_12V );
    AdcInitChannel( &obj->ADC_24V_obj, ADC_24V );
    AdcInitChannel( &obj->Isense_12V_1_obj, Isense_12V_1 );
    AdcInitChannel( &obj->Isense_12V_2_obj, Isense_12V_2 );
    AdcInitChannel( &obj->Isense_12V_3_obj, Isense_12V_3 );
    AdcInitChannel( &obj->Isense_24V_obj, Isense_24V );
    AdcInitChannel( &obj->Isense_485_VCC1_obj, Isense_485_VCC1 );
    AdcInitChannel( &obj->Isense_485_VCC2_obj, Isense_485_VCC2 );

    obj->IsInitialized = true;

    return BSP_SUCCESS;
}

/**
 * @brief 智慧电源ADC检测读取
 * @param  obj         电源ADC检测对象
 */
int8_t drv_pcuAdc_Get( pcuAdc_t *obj )
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;
    
    if (!obj->IsInitialized)
    {
        log_e( "drv_pcuAdc has no Initialized\r\n" );
        return BSP_ERROR_NO_INIT;
    }

    xSemaphoreTake( obj->Lock, portMAX_DELAY );
    obj->V_TC = ntc_get_temp(&obj->ADC_TC_obj);
    obj->V_12V = AdcReadChannelVol( &obj->ADC_12V_obj ) * 11;
    obj->V_24V = AdcReadChannelVol( &obj->ADC_24V_obj ) * 21;
    obj->I_12V_1 = AdcReadChannelVol( &obj->Isense_12V_1_obj );
    obj->I_12V_2 = AdcReadChannelVol( &obj->Isense_12V_2_obj );
    obj->I_12V_3 = AdcReadChannelVol( &obj->Isense_12V_3_obj );
    obj->I_24V = AdcReadChannelVol( &obj->Isense_24V_obj ) * 2;
    obj->I_485_VCC1 = AdcReadChannelVol( &obj->Isense_485_VCC1_obj );
    obj->I_485_VCC2 = AdcReadChannelVol( &obj->Isense_485_VCC2_obj );

#if PCU_DC_CALIBRATION
    if (obj->V_12V > 10)
        obj->V_12V = obj->V_12V * 1.845 - 7.79;

    if (obj->V_24V > 17)
        obj->V_24V = 0.1845 * obj->V_24V * obj->V_24V - 4.9837 * obj->V_24V + 49.258;
#endif

    xSemaphoreGive( obj->Lock );

    return BSP_SUCCESS;
}

/**
 * @brief 智慧电源DAC调光初始化
 * @param  obj         DAC调光对象
 */
int8_t drv_pcuDac_init( pcuDac_t *obj )
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;
    
    if (obj->IsInitialized)
    {
        log_e( "drv_pcuDac_init error: has already Initialized\r\n" );
        return BSP_ERROR_ALREADY_INIT;
    }

    obj->Lock = xSemaphoreCreateBinary();  /* 初始时信号值为0 */
    if(obj->Lock == NULL)
        return BSP_ERROR_NO_MEM;
    xSemaphoreGive( obj->Lock );

    DacInit( &obj->dac1_obj, DAC1_PIN );
    DacInit( &obj->dac2_obj, DAC2_PIN );

    obj->IsInitialized = true;

    return BSP_SUCCESS;
}

/**
 * @brief 智慧电源DAC调光设置
 * @param  obj         DAC调光对象
 * @param  value1      通道1调光电压（0-10）
 * @param  value2      通道2调光电压（0-10）
 */
int8_t drv_pcuDac_Set( pcuDac_t *obj, float value1, float value2 )
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;
    
    if (!obj->IsInitialized)
    {
        log_e( "drv_pcuDac has no Initialized\r\n" );
        return BSP_ERROR_NO_INIT;
    }

    xSemaphoreTake( obj->Lock, portMAX_DELAY );
    if ( ( value1 >= 0 ) && ( value1 <= 10 ) )
    {
        DacSetVol( &obj->dac1_obj, (float)(value1/8) );
        obj->vol1 = value1;
    }
    if ( ( value2 >= 0 ) && ( value2 <= 10 ) )
    {
        DacSetVol( &obj->dac2_obj, (float)(value2/8) );
        obj->vol2 = value2;
    }
    xSemaphoreGive( obj->Lock );

    return BSP_SUCCESS; 
}

/**
 * @brief 智慧电源DI检测读取
 * @param  obj         电源DI检测对象
 */
int8_t drv_pwrDect_init( pwrDect_t *obj )
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;
    
    if (obj->IsInitialized)
    {
        log_e( "drv_pwrDect error: has already Initialized\r\n" );
        return BSP_ERROR_ALREADY_INIT;
    }

    obj->Lock = xSemaphoreCreateBinary();  /* 初始时信号值为0 */
    if(obj->Lock == NULL)
        return BSP_ERROR_NO_MEM;
    xSemaphoreGive( obj->Lock );

    GpioInit( &obj->BAT_CTRL_obj, BAT_CTRL, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
    GpioInit( &obj->Power_DECT1_obj, Power_DECT1, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
    GpioInit( &obj->Power_DECT2_obj, Power_DECT2, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
    GpioInit( &obj->Power_DECT3_obj, Power_DECT3, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
    GpioInit( &obj->Power_DECT4_obj, Power_DECT4, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );
    GpioInit( &obj->Power_DECT5_obj, Power_DECT5, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 );

    obj->IsInitialized = true;

    return BSP_SUCCESS;
}

/**
 * @brief 智慧电源DI状态读取
 * @param  obj         电源DI检测对象
 */
int8_t drv_pwrDect_Get( pwrDect_t *obj )
{
    if (obj == NULL)
        return BSP_ERROR_INVALID_PARAM;
    
    if (!obj->IsInitialized)
    {
        log_e( "drv_pcuAdc has no Initialized\r\n" );
        return BSP_ERROR_NO_INIT;
    }

    xSemaphoreTake( obj->Lock, portMAX_DELAY );
    obj->v_BAT_CTRL = GpioRead( &obj->BAT_CTRL_obj );
    obj->v_Power_DECT1 = GpioRead( &obj->Power_DECT1_obj );
    obj->v_Power_DECT2 = GpioRead( &obj->Power_DECT2_obj );
    obj->v_Power_DECT3 = GpioRead( &obj->Power_DECT3_obj );
    obj->v_Power_DECT4 = GpioRead( &obj->Power_DECT4_obj );
    obj->v_Power_DECT5 = GpioRead( &obj->Power_DECT5_obj );
    xSemaphoreGive( obj->Lock );

    return BSP_SUCCESS;
}


#include "drv_hc595_pcu.h"

static SemaphoreHandle_t pcuPwrCtrLock;
/**
 * @brief 智慧电源电源输出控制初始化
 */
void drv_pcuPwrCtr_init( void )
{
    pcuPwrCtrLock = xSemaphoreCreateBinary();  /* 初始时信号值为0 */
    if(pcuPwrCtrLock == NULL)
        return;
    xSemaphoreGive( pcuPwrCtrLock );

    drv_pwrCtr_init();
    drv_pcuPwrCtr_Set( PCU_PWR_ALL_SET, 1 );    /* 开机全开 */
}

static bool pcu_acctr_state = false;
/**
 * @brief 电源输出控制
 * @param  mask        PCU_XX_SET 的组合
 * @param  state       0:置低，非0：置高
 * @par 示例:
 * @code
 *    drv_pwrCtr_Set( PCU_24V_SET | PCU_12VOUT1_SET | PCU_485_VCC2_SET );
 * @endcode
 */
void drv_pcuPwrCtr_Set( uint8_t mask, uint8_t state )
{
    xSemaphoreTake( pcuPwrCtrLock, portMAX_DELAY );

    if (mask & PCU_AC_Ctr_SET)
    {
        if (state == 0)
        {
            drv_pwrCtr_Set( PCU_AC_Ctr_OFF, 1 );
            vTaskDelay(200);
            drv_pwrCtr_Set( PCU_AC_Ctr_OFF, 0 );
            pcu_acctr_state = false;
        }
        else
        {
            drv_pwrCtr_Set( PCU_AC_Ctr_ON, 1 );
            vTaskDelay(200);
            drv_pwrCtr_Set( PCU_AC_Ctr_ON, 0 );
            pcu_acctr_state = true;
        }
    }

    mask &= 0x3F;
    drv_pwrCtr_Set( mask, state );

    xSemaphoreGive( pcuPwrCtrLock );
}

/**
 * @brief 获取电源输出当前状态
 */
void drv_pcuPwrCtr_Get( uint8_t *mask )
{
    xSemaphoreTake( pcuPwrCtrLock, portMAX_DELAY );

    drv_pwrCtr_Get( mask );
    *mask &= 0x3F;
    if (pcu_acctr_state)
        *mask |= PCU_AC_Ctr_SET;

    xSemaphoreGive( pcuPwrCtrLock );
}

/*********** (C) COPYRIGHT 2020 FiberHome *****END OF FILE****/
